import com.mochimedia.ui.Cell;
import com.mochimedia.ui.Component;

/**
* ...
* @author $(DefaultUser)
*/

class com.mochimedia.ui.Position {
    
    public static var ALIGN_LEFT:Number = 1;
    public static var ALIGN_CENTER:Number = 2;
    public static var ALIGN_RIGHT:Number = 3;
    
    public static var PLACEMENT_NORMAL:Number = 4;
    public static var PLACEMENT_FLOAT:Number = 5;
    public static var PLACEMENT_FLOAT_RIGHT:Number = 6;
    public static var PLACEMENT_ABSOLUTE:Number = 7;
    
    public static var CLEAR_NONE:Number = 8;
    public static var CLEAR_LEFT:Number = 9;
    public static var CLEAR_RIGHT:Number = 10;
    public static var CLEAR_BOTH:Number = 11;
    
    public static var ORIENTATION_HORIZONTAL:Number = 12;
    public static var ORIENTATION_VERTICAL:Number = 13;
    
    private var _align:Number;
    private var _placement:Number;
    private var _clear:Number;
	
	public static var defaultMarginTop:Number = 0;
	public static var defaultMarginRight:Number = 0;
	public static var defaultMarginBottom:Number = 0;
	public static var defaultMarginLeft:Number = 0;
    
    private var _margin:Number = 0;
    private var _margin_top:Number = 0;
    private var _margin_right:Number = 0;
    private var _margin_bottom:Number = 0;
    private var _margin_left:Number = 0;
    
    private var _top:Number = 0;
    private var _left:Number = 0;
    
    private var _zindex:Number = 1;
    
    private var _collapse:Boolean = false;
    
    public function get align():Number { return _align; }
    public function set align(value:Number):Void { _align = value; }
    
    public function get placement():Number { return _placement; }
    
    public function get clear():Number { return _clear; }
    
    public function get margin():Number { return _margin; }

    public function get margin_top():Number { return _margin_top; }

    public function get margin_right():Number { return _margin_right; }

    public function get margin_bottom():Number { return _margin_bottom; }

    public function get margin_left():Number { return _margin_left; }
    
    public function get top():Number { return _top; }
    public function set top(value:Number):Void { _top = value; }
    
    public function get left():Number { return _left; }
    public function set left(value:Number):Void { _left = value; }
    
    public function get zindex():Number { return _zindex; }
    public function set zindex(value:Number):Void { _zindex = value; }
    
    public function get collapse():Boolean { return _collapse; }
       
    private var _options:Object;
    
    //
    //
    public function Position (options:Object, align:Number, placement:Number, clear:Number, margins:Object, top:Number, left:Number, zindex:Number, collapse:Boolean) {
        
        _options = options;
        
        _align = (!isNaN(options.align)) ? options.align : (!isNaN(align)) ? align : ALIGN_LEFT;
        _placement = (!isNaN(options.placement)) ? options.placement : (!isNaN(placement)) ? placement : PLACEMENT_NORMAL;
        _clear = (!isNaN(options.clear)) ? options.clear : (!isNaN(clear)) ? clear : (_placement == PLACEMENT_FLOAT || _placement == PLACEMENT_FLOAT_RIGHT) ? CLEAR_NONE : CLEAR_BOTH;

        _top = (!isNaN(options.top)) ? options.top : (!isNaN(top)) ? top : _top;
        _left = (!isNaN(options.left)) ? options.left : (!isNaN(left)) ? left : _left;
        _zindex = (!isNaN(options.zindex)) ? options.zindex : (!isNaN(zindex)) ? zindex : _zindex;
        _collapse = (options.collapse == true || collapse == true);

        if (options.margins != undefined) margins = options.margins;
        
        if (margins != undefined) {
            
            if (typeof(margins) == "number") {
                
                _margin = _margin_top = _margin_right = _margin_bottom = _margin_left = Number(margins);
                
            } else {
                
                var m:Array;
                
                if (typeof(margins) == "string") m = String(margins).split(" ");
                else m = Array(margins);
                
                _margin_top = (!isNaN(m[0])) ? parseInt(m[0]) : 0;
                _margin_right = (!isNaN(m[1])) ? parseInt(m[1]) : 0;
                _margin_bottom = (!isNaN(m[2])) ? parseInt(m[2]) : 0;
                _margin_left = (!isNaN(m[3])) ? parseInt(m[3]) : 0;
                
            }
        
        } else {
				
			_margin_top = defaultMarginTop;
			_margin_right = defaultMarginRight;
			_margin_bottom = defaultMarginBottom;
			_margin_left = defaultMarginLeft;
				
		}
        
        if (options.margin_top != undefined) _margin_top = options.margin_top;
        if (options.margin_right != undefined) _margin_right = options.margin_right;
        if (options.margin_bottom != undefined) _margin_bottom = options.margin_bottom;
        if (options.margin_left != undefined) _margin_left = options.margin_left;
        
    }
    
    //
    //
    public function clone (overrides:Object):Position {
        
        var optCopy = { };
        
        for (var param:String in _options) optCopy[param] = _options[param];
        for (var param:String in this) {
            if (param.indexOf("_") == 0) {
                if (typeof(this[param]) == "string" || typeof(this[param]) == "number") {
                    optCopy[param] = this[param];
                }
            }
        }
        for (var param:String in overrides) optCopy[param] = overrides[param];
        return new Position(optCopy);
        
    }
    
    //
    //
    public static function arrangeContent (cell:Cell, clear:Boolean):Void {
        
        if (clear) {
            cell.lastArrangedChildIndex = -1;
            cell.lastArrangedChildX = 0;
            cell.lastArrangedChildY = 0;
        }
        
        var prevChild:Component;
        var child:Component;
        var ypos:Number = cell.lastArrangedChildY;
        var rowItems:Array = [];
            
        for (var i:Number = cell.lastArrangedChildIndex + 1; i < cell.childNodes.length; i++) {
            
            child = cell.childNodes[i];

            if (child.position.placement != prevChild.position.placement || child.position.clear == CLEAR_LEFT || child.position.clear == CLEAR_BOTH || prevChild.position.clear == CLEAR_RIGHT|| prevChild.position.clear == CLEAR_BOTH) {
                
                if (rowItems.length > 0) {
                    if ((child.position.clear == CLEAR_NONE || child.position.clear == CLEAR_RIGHT) && (prevChild.position.clear == CLEAR_NONE || prevChild.position.clear == CLEAR_LEFT)) {
                        alignRow(cell, rowItems, cell.position.align);
                    } else {
                        ypos += alignRow(cell, rowItems, cell.position.align);
                        cell.lastArrangedChildY = ypos;
                        cell.lastArrangedChildIndex = i - 1;
                    }
                    rowItems = [];
                }
                
            }
            
            switch (child.position.placement) {
    
                case PLACEMENT_FLOAT:
            
                    child.x = child.position.margin_left;
                    child.y = child.position.margin_top + ypos;
                    rowItems.push(child);
                    break;
                    
                case PLACEMENT_FLOAT_RIGHT:
                
                    child.x = cell.width - child.width - cell.position.margin_right;
                    child.y = child.position.margin_top + ypos;
                    rowItems.push(child);
                    break;              
                    
                case PLACEMENT_ABSOLUTE:
                
                    child.x = child.position.left;
                    child.y = child.position.top;
                    break;
                    
                case PLACEMENT_NORMAL:
                
                    switch (cell.position.align) {
                        case Position.ALIGN_LEFT:
                            child.x = child.position.margin_left;
                            break;
                        case Position.ALIGN_CENTER:
                            child.x = Math.floor(cell.width * 0.5 - child.width * 0.5);
                            break;
                        case Position.ALIGN_RIGHT:
                            child.x = cell.width - child.width;
                            break;
                    }
                    child.y = child.position.margin_top + ypos;
                    ypos += child.position.margin_top + child.height + child.position.margin_bottom;
                    cell.lastArrangedChildY = ypos;
                    cell.lastArrangedChildIndex = i;
                    break;
                    
            }
            
            prevChild = child;
            
        }
        
        if (rowItems.length > 0) alignRow(cell, rowItems, cell.position.align);
        
        if (cell.sortChildNodes) zSort(cell);

    }
    
    //
    //
    private static function alignRow (cell:Cell, children:Array, alignment:Number):Number {
        
        var child:Component;
        var xpos:Number = cell.lastArrangedChildX;
        var height:Number = 0;
        var margin_bottom:Number = -20;
        var yoffset:Number = 0;
        
        if (children[0].position.placement == PLACEMENT_FLOAT_RIGHT) alignment = ALIGN_RIGHT;

        switch (alignment) {
            
            case ALIGN_CENTER:
            
                var totalWidth:Number = 0;
                
                for (var i:Number = children.length - 1; i >= 0; i--) {
                    child = children[i];
                    totalWidth += child.width + Math.max(child.position.margin_right, child.position.margin_left);
                }
                
                totalWidth -= Math.max(child.position.margin_right, child.position.margin_left);
                
                xpos = Math.floor(cell.width * 0.5 - totalWidth * 0.5);
                
                // xpos set, now continue to ALIGN_LEFT ...
				
            case ALIGN_LEFT:
            default:
                
                for (var i:Number = 0; i < children.length; i++) {
                    
                    child = children[i];
                    
                    child.x = child.position.margin_left + xpos;
					child.y += yoffset;
					
                    xpos += child.position.margin_left + child.width + child.position.margin_right;
                    
                    if (child.x + child.width > child.parentCell.width) {
                        child.x = 0;
                        xpos = 0;
                        child.y += child.height;
                        yoffset = child.height;
                    }
                    
                    height = Math.max(yoffset + child.height, height);
                    margin_bottom = Math.max(child.position.margin_bottom, margin_bottom);
                    
                }
                
                break;
            
            case ALIGN_RIGHT:
            
                xpos = cell.width;

                for (var i:Number = children.length - 1; i >= 0; i--) {
                    
                    child = children[i];
                    child.x = xpos - child.width - child.position.margin_right;
                    xpos -= child.position.margin_left + child.width + child.position.margin_right; 
                    height = Math.max(child.height, height);
                    margin_bottom = Math.max(child.position.margin_bottom, margin_bottom);
                    
                }
            
                break;
                
        }
        
        return height + margin_bottom;
        
    }
    
    private static function zSort (cell:Cell):Void {
        
        var zChildren:Array = cell.childNodes.concat();
        
        zChildren.sort(function (a, b):Number {
            
            var c1:Component = Component(a);
            var c2:Component = Component(b);

            if (c1.zindex < c2.zindex) return -1;
            else if (c1.zindex > c2.zindex) return 1;
            else return 0;
            
            });
            
        var cclip:MovieClip;
        var pclip:MovieClip;
        
        for (var i:Number = zChildren.length - 1; i > 0; i--) {
            
            cclip = MovieClip(zChildren[i]["_mc"]);
            pclip = MovieClip(zChildren[i - 1]["_mc"]);

            cclip.swapDepths(i);
            
        }       
        
    }
    
    //
    //
    public static function getCellContentWidth (cell:Cell):Number {
        
        var width:Number = 0;
        
        for (var i:Number = cell.childNodes.length - 1; i >= 0; i--) {
            
            width = Math.floor(Math.max(width, Component(cell.childNodes[i]).x + Component(cell.childNodes[i]).width));
            
        }
        
        return width;
        
    }
    
    //
    //
    public static function getCellContentHeight (cell:Cell):Number {
        
        var height:Number = 0;
        var childNum:Number = cell.childNodes.length - 1;
        var lastChild:Component = cell.childNodes[childNum];
        
        while (lastChild.position.placement == Position.PLACEMENT_ABSOLUTE && childNum > 0) {
        
            childNum--;
            lastChild = cell.childNodes[childNum];
        
        }
        
        if (lastChild != undefined) {
            
            height = Math.floor(lastChild.y + lastChild.height + lastChild.position.margin_bottom);
			
			if (cell.collapse) height += lastChild.style.padding;
            
        }
        
        if (isNaN(height)) height = 0;
        
        return height;
        
    }
    
}